home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / daemons / ipServer / sockOps.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-19  |  53.4 KB  |  2,081 lines

  1. /* 
  2.  * sockOps.c --
  3.  *
  4.  *    Routines to handle operations on sockets. The various operations
  5.  *    include creating and destroying a socket, reading and writing,
  6.  *    assigning local and remote addresses of a socket, connecting to
  7.  *    remote hosts and accepting connections from remote hosts.
  8.  *    Most of the routines in this file validate arguments and have
  9.  *    protocol-dependent routines handle the semantics of the operation.
  10.  *
  11.  *    The routines in this file manipulate socket state information.
  12.  *    The state information is stored in 2 different data structures 
  13.  *    because some of the information can be shared among all clients 
  14.  *    sharing the socket while a portion must be private to each client.
  15.  *    Private information includes such things as the client's PID and 
  16.  *    host ID, and values of flags to emulate the recvfrom and sento 
  17.  *    calls. For each client sharing a socket, their Sock_PrivInfo 
  18.  *    struct points to a Sock_SharedInfo struct. The shared state includes
  19.  *    the send and receive buffers, the local and remote addresses, and
  20.  *    protocol-specific information.
  21.  *
  22.  *    All sockets with the same type are kept on a linked list.
  23.  *
  24.  *    To do:
  25.  *    1) stronger validation of token in ACCEPT_CONN_2 ioctl.
  26.  *    2) complete get/set options.
  27.  *
  28.  * Copyright 1987 Regents of the University of California
  29.  * All rights reserved.
  30.  * Permission to use, copy, modify, and distribute this
  31.  * software and its documentation for any purpose and without
  32.  * fee is hereby granted, provided that the above copyright
  33.  * notice appear in all copies.  The University of California
  34.  * makes no representations about the suitability of this
  35.  * software for any purpose.  It is provided "as is" without
  36.  * express or implied warranty.
  37.  */
  38.  
  39. #ifndef lint
  40. static char rcsid[] = "$Header: /sprite/src/daemons/ipServer/RCS/sockOps.c,v 1.21 91/08/13 23:33:05 mottsmth Exp $ SPRITE (Berkeley)";
  41. #endif not lint
  42.  
  43.  
  44. #include "sprite.h"
  45. #include "dev/net.h"
  46. #include "ipServer.h"
  47. #include "stat.h"
  48. #include "socket.h"
  49. #include "sockInt.h"
  50. #include "tcp.h"
  51. #include "udp.h"
  52. #include "raw.h"
  53.  
  54. #include "fs.h"
  55. #include "dev/pdev.h"
  56.  
  57. /*
  58.  * The value of the socket address family used by Unix sockets. 
  59.  * It is not used by Sprite programs.
  60.  */
  61. #define AF_INET    2
  62.  
  63. /*
  64.  * Basic operations on sockets that must do protocol-dependent processing.
  65.  * Only some of the operations are defined for some protocols.
  66.  */
  67. typedef struct {
  68.     ReturnStatus    (*open)();    /* Create and initialize a socket. */
  69.     ReturnStatus    (*close)();    /* Close and destroy a socket. */
  70.     ReturnStatus    (*read)();    /* Read data from the peer. */
  71.     ReturnStatus    (*write)();    /* Write data to the peer. */
  72.     int            (*select)();    /* See if the socket is ready. */
  73.     ReturnStatus    (*bind)();    /* Assign a local address. */
  74.     ReturnStatus    (*listen)();    /* Make into a passive socket. */
  75.     ReturnStatus    (*accept)();    /* On a passive socket, accept the first
  76.                      * remote connection request. */
  77.     ReturnStatus    (*connect)();    /* Create a virtual circuit to a remote
  78.                      * host. */
  79.     ReturnStatus    (*shutdown)();    /* Close a virtual circuit gracefully.*/
  80.     void        (*destroy)();    /* Destroy a socket. */
  81.     ReturnStatus    (*getOption)();    /* Get the value of an option. */
  82.     ReturnStatus    (*setOption)();    /* Set the value of an option. */
  83. } SocketOps;
  84.  
  85. /*
  86.  * Information kept for each type of supported protocol.
  87.  */
  88. typedef struct {
  89.     List_Links    list;    /* All sockets for the protocol are linked
  90.              * together on this queue. */
  91.     SocketOps    ops;    /* Ptrs to basic functions for the protocol. */
  92. } ProtocolInfo;
  93.  
  94. static ProtocolInfo    protoInfo[1 + MAX_PROTO_INDEX];
  95.  
  96.  
  97. Sock_SharedInfo *curSock;
  98.  
  99.  
  100. /*
  101.  * A hack to convert a clientID into a Sock_PrivInfo ptr for dups.
  102.  */
  103.  
  104. #define NUM_SOCKETS 256
  105. static struct {
  106.     int clientID;
  107.     Sock_PrivInfo *privPtr;
  108. } openSockets[NUM_SOCKETS];
  109.  
  110.  
  111. /* Forward references. */
  112. static ReturnStatus    HandleGenericIOC();
  113. static ReturnStatus    GetOption();
  114. static ReturnStatus    SetOption();
  115.  
  116. /*
  117.  * Placeholder routines for protocols that don't handle some of 
  118.  * the operations in the SocketOps structure.
  119.  */
  120. static void         NoOp();
  121. static ReturnStatus    DummyOp();
  122. static ReturnStatus    BadOp();
  123.  
  124.  
  125.  
  126. /*
  127.  *----------------------------------------------------------------------
  128.  *
  129.  * Sock_MemBin --
  130.  *
  131.  *    Calls Mem_Bin to optimize allocation of Sock structures.
  132.  *
  133.  * Results:
  134.  *    None.
  135.  *
  136.  * Side effects:
  137.  *    As above.
  138.  *
  139.  *----------------------------------------------------------------------
  140.  */
  141.  
  142. void
  143. Sock_MemBin()
  144. {
  145.     Mem_Bin(sizeof(Sock_BufDataInfo));
  146.     Mem_Bin(sizeof(Sock_SharedInfo));
  147.     Mem_Bin(sizeof(Sock_PrivInfo));
  148. }
  149.  
  150.  
  151. /*
  152.  *----------------------------------------------------------------------
  153.  *
  154.  * Sock_Init --
  155.  *
  156.  *    Initializes the socket-related data structures and routines.
  157.  *
  158.  * Results:
  159.  *    None.
  160.  *
  161.  * Side effects:
  162.  *    The protocol-dependent information struct is initialized.
  163.  *
  164.  *----------------------------------------------------------------------
  165.  */
  166.  
  167. void
  168. Sock_Init()
  169. {
  170.     register ProtocolInfo    *protoPtr;
  171.  
  172.     if (ips_Debug) {
  173.     (void) fprintf(stderr, "Sock: sizeof(Sock_SharedInfo) = %d\n", 
  174.                 sizeof(Sock_SharedInfo));
  175.     (void) fprintf(stderr, "Sock: sizeof(Sock_PrivInfo) = %d\n", 
  176.                 sizeof(Sock_PrivInfo));
  177.     }
  178.  
  179.     protoPtr = &(protoInfo[RAW_PROTO_INDEX]);
  180.     List_Init(&(protoPtr->list));
  181.     protoPtr->ops.open        = Raw_SocketOpen;
  182.     protoPtr->ops.close        = Raw_SocketClose;
  183.     protoPtr->ops.read        = Raw_SocketRead;
  184.     protoPtr->ops.write        = Raw_SocketWrite;
  185.     protoPtr->ops.select    = Raw_SocketSelect;
  186.     protoPtr->ops.bind        = Raw_SocketBind;
  187.     protoPtr->ops.connect    = Raw_SocketConnect;
  188.     protoPtr->ops.listen    = BadOp;
  189.     protoPtr->ops.accept    = BadOp;
  190.     protoPtr->ops.shutdown    = Raw_SocketShutdown;
  191.     protoPtr->ops.destroy    = NoOp;
  192.     protoPtr->ops.getOption    = DummyOp;
  193.     protoPtr->ops.setOption    = DummyOp;
  194.  
  195.     protoPtr = &(protoInfo[UDP_PROTO_INDEX]);
  196.     List_Init(&(protoPtr->list));
  197.     protoPtr->ops.open        = UDP_SocketOpen;
  198.     protoPtr->ops.close        = UDP_SocketClose;
  199.     protoPtr->ops.read        = UDP_SocketRead;
  200.     protoPtr->ops.write        = UDP_SocketWrite;
  201.     protoPtr->ops.select    = UDP_SocketSelect;
  202.     protoPtr->ops.bind        = UDP_SocketBind;
  203.     protoPtr->ops.connect    = UDP_SocketConnect;
  204.     protoPtr->ops.listen    = BadOp;
  205.     protoPtr->ops.accept    = BadOp;
  206.     protoPtr->ops.shutdown    = UDP_SocketShutdown;
  207.     protoPtr->ops.destroy    = NoOp;
  208.     protoPtr->ops.getOption    = DummyOp;
  209.     protoPtr->ops.setOption    = DummyOp;
  210.  
  211.     protoPtr = &(protoInfo[TCP_PROTO_INDEX]);
  212.     List_Init(&(protoPtr->list));
  213.     protoPtr->ops.open        = TCP_SocketOpen;
  214.     protoPtr->ops.close        = TCP_SocketClose;
  215.     protoPtr->ops.read        = TCP_SocketRead;
  216.     protoPtr->ops.write        = TCP_SocketWrite;
  217.     protoPtr->ops.select    = TCP_SocketSelect;
  218.     protoPtr->ops.bind        = TCP_SocketBind;
  219.     protoPtr->ops.connect    = TCP_SocketConnect;
  220.     protoPtr->ops.listen    = TCP_SocketListen;
  221.     protoPtr->ops.accept    = TCP_SocketAccept;
  222.     protoPtr->ops.shutdown    = TCP_SocketShutdown;
  223.     protoPtr->ops.destroy    = TCP_SocketDestroy;
  224.     protoPtr->ops.getOption    = TCP_SocketGetOpt;
  225.     protoPtr->ops.setOption    = TCP_SocketSetOpt;
  226. }
  227.  
  228. /*
  229.  *----------------------------------------------------------------------
  230.  *
  231.  * Sock_Open --
  232.  *
  233.  *    Allocate and initialize the Sock_PrivInfo and Sock_SharedInfo 
  234.  *    structures for the new socket.
  235.  *
  236.  * Results:
  237.  *    None.
  238.  *
  239.  * Side effects:
  240.  *    Memory for the structures is allocated. The structures are 
  241.  *    initialized and the Sock_SharedInfo struct is added to a queue 
  242.  *    of sockets with the same protocol.
  243.  *
  244.  *----------------------------------------------------------------------
  245.  */
  246.  
  247. static char *protoNames[] = { "Raw", "UDP", "TCP"};
  248.  
  249. ReturnStatus
  250. Sock_Open(sockPdevPtr, isNewOpen, streamID, fsFlags, 
  251.         pid, hostID, userID, clientID, privPtrPtr)
  252.     SockPdevState *sockPdevPtr;    /* Contains protocol # and info about the
  253.                  * pseudo-device request buffer */
  254.     Boolean     isNewOpen;    /* If TRUE, the client is opening the socket
  255.                  * for the first time. Otherwise, it's a 
  256.                  * dup. operation due to a fork. */
  257.     int        streamID;    /* Stream ID of the psuedo-device. */
  258.     int        fsFlags;    /* Flags passed to Fs_Open by client. */
  259.     Proc_PID    pid;        /* Process ID of the client. */
  260.     int        hostID;        /* Host ID of client's machine. */
  261.     int        userID;        /* User ID of the client. */
  262.     int        clientID;    /* Unique ID for the client. */
  263.     Sock_PrivInfo **privPtrPtr;    /* Out: ptr to the Sock_PrivInfo struct just 
  264.                  *  created.*/
  265. {
  266.     ReturnStatus status;
  267.     register Sock_PrivInfo    *privPtr;
  268.     register Sock_SharedInfo    *sharePtr;
  269.     register int        protoIndex = sockPdevPtr->protoIndex;
  270.  
  271.     stats.sock.open++;
  272.     *privPtrPtr = (Sock_PrivInfo *)NULL;
  273.  
  274.     if (ips_Debug) {
  275.     (void) fprintf(stderr,"Sock_Open(%d,%d,%x): %s  %s\n", 
  276.         streamID, clientID, pid, 
  277.         isNewOpen?"new":"dup", protoNames[protoIndex]);
  278.     }
  279.  
  280.     if (protoIndex < 0 || protoIndex > MAX_PROTO_INDEX) {
  281.     panic("Sock_Open: illegal protoIndex %d\n", protoIndex);
  282.     }
  283.  
  284.     privPtr = (Sock_PrivInfo *) malloc(sizeof(Sock_PrivInfo));
  285.     bzero((Address) privPtr, sizeof(Sock_PrivInfo) );
  286. #ifndef KERNEL
  287.     privPtr->streamID    = streamID;
  288. #endif
  289.     privPtr->fsFlags    = fsFlags;
  290.     privPtr->pid    = pid;
  291.     privPtr->hostID    = hostID;
  292.     privPtr->userID    = userID;
  293.     privPtr->clientID    = clientID;
  294.     privPtr->recvFlags    = 0;
  295.     privPtr->sendInfoValid = FALSE;
  296.     List_InitElement(&privPtr->links);
  297.  
  298.     if (!isNewOpen) {
  299.     fprintf(stderr, "Sock_Open: got obsolete dup request.\n");
  300.     exit(1);
  301.     }
  302.  
  303.     /*
  304.      * Create the shared socket state.
  305.      */
  306.  
  307.     sharePtr = (Sock_SharedInfo *) malloc(sizeof(Sock_SharedInfo));
  308.     bzero( (Address) sharePtr, sizeof(Sock_SharedInfo));
  309.  
  310.     sharePtr->protoData    = (ClientData) NULL;
  311.     sharePtr->protoIndex    = protoIndex;
  312.     sharePtr->requestBuf    = sockPdevPtr->requestBuf;
  313.     sharePtr->reqBufSize    = sockPdevPtr->reqBufSize;
  314.     sharePtr->state        = CREATED;
  315.     sharePtr->flags        = 0;
  316.     sharePtr->owner.id    = 0;
  317.     sharePtr->options    = NET_OPT_BROADCAST;
  318.     sharePtr->clientCount    = 1;
  319.     sharePtr->local.port    = 0;
  320.     sharePtr->local.address    = Net_HostToNetInt(NET_INET_ANY_ADDR);
  321.     sharePtr->remote.port    = 0;
  322.     sharePtr->remote.address = Net_HostToNetInt(NET_INET_ANY_ADDR);
  323.     sharePtr->linger    = 0;
  324.     sharePtr->justEstablished    = FALSE;
  325.     List_Init(&sharePtr->clientList);
  326.     List_InitElement(&sharePtr->protoLinks);
  327.     List_Insert(&sharePtr->protoLinks,
  328.             LIST_ATREAR(&protoInfo[protoIndex].list));
  329.     privPtr->sharePtr = sharePtr;
  330. #ifndef KERNEL
  331.     openSockets[streamID].clientID = clientID;
  332.     openSockets[streamID].privPtr = privPtr;
  333. #endif
  334.  
  335.     /*
  336.      * Now call the protocol-dependent open routine. It may reject
  337.      * the open by returning a non-SUCCESS status.
  338.      */
  339.  
  340.     status = protoInfo[protoIndex].ops.open(sharePtr, userID);
  341. #ifdef lint
  342.     status = TCP_SocketOpen(sharePtr, userID);
  343.     status = UDP_SocketOpen(sharePtr, userID);
  344.     status = Raw_SocketOpen(sharePtr, userID);
  345. #endif
  346.  
  347.     if (status == SUCCESS) {
  348.     *privPtrPtr = privPtr;
  349.     List_Insert(&privPtr->links, LIST_ATREAR(&sharePtr->clientList));
  350.     curSock = sharePtr;
  351.     } else {
  352.     free((char *) privPtr);
  353.     if (sharePtr != (Sock_SharedInfo *) NULL) {
  354.         if (sharePtr->clientCount == 1) {
  355.         List_Remove(&sharePtr->protoLinks);
  356.         free((char *) sharePtr);
  357.         }
  358.         openSockets[streamID].clientID = 0;
  359.     }
  360.     }
  361.  
  362.     return(status);
  363. }
  364.  
  365. /*
  366.  *----------------------------------------------------------------------
  367.  *
  368.  * Sock_Close --
  369.  *
  370.  *    Clean up state associated with the socket if the protocol-dependent
  371.  *    routine says it's OK.
  372.  *
  373.  * Results:
  374.  *    SUCCESS        - the socket has been destroyed.
  375.  *    FS_WOULD_BLOCK    - the socket is in the processing of closing.
  376.  *
  377.  * Side effects:
  378.  *    Memory for the socket structure may be freed.
  379.  *
  380.  *----------------------------------------------------------------------
  381.  */
  382.  
  383. ReturnStatus
  384. Sock_Close(privPtr)
  385.     Sock_PrivInfo    *privPtr;    /* Socket to be closed. */
  386. {
  387.     register Sock_SharedInfo *sharePtr;
  388.     ReturnStatus    status;
  389.  
  390.     stats.sock.close++;
  391.  
  392. #ifndef KERNEL
  393.     if (ips_Debug) {
  394.     (void) fprintf(stderr, "Sock_Close(%d,%d,%x)\n",
  395.         privPtr->streamID, privPtr->clientID, privPtr->pid);
  396.     }
  397.     openSockets[privPtr->streamID].clientID = 0;
  398. #endif
  399.     List_Remove(&privPtr->links);
  400.  
  401.     sharePtr = privPtr->sharePtr;
  402.  
  403.     if (sharePtr->clientCount > 1) {
  404.     (void) fprintf(stderr, "Sock_Close got clientCount > 1 (%d)\n",
  405.         sharePtr->clientCount);
  406.     exit(1);
  407.     }
  408.  
  409.     status = protoInfo[sharePtr->protoIndex].ops.close(sharePtr);
  410. #ifdef lint
  411.     status = TCP_SocketClose(sharePtr);
  412.     status = UDP_SocketClose(sharePtr);
  413.     status = Raw_SocketClose(sharePtr);
  414. #endif
  415.     /*
  416.      * Clean up the socket structure.  A TCP connection
  417.      * might be lingering in the close protocol so we don't
  418.      * always nuke the socket descriptor.
  419.      */
  420.     sharePtr->clientCount--;
  421.     free((char *) privPtr);
  422.     if (sharePtr->requestBuf != (char *) NIL) {
  423.     free((char *) sharePtr->requestBuf);
  424.     sharePtr->requestBuf = (char *)NIL;
  425.     }
  426.     if (status == SUCCESS) {
  427.     List_Remove(&sharePtr->protoLinks);
  428.     free((char *) sharePtr);
  429.     }
  430.  
  431.     return(status);
  432. }
  433.  
  434. /*
  435.  *----------------------------------------------------------------------
  436.  *
  437.  * Sock_Read --
  438.  *
  439.  *    Supply data to the client's Fs_Read call.
  440.  *
  441.  * Results:
  442.  *    SUCCESS            - the operation was successful.
  443.  *    NET_BAD_OPERATION    - the socket was not in a state that could
  444.  *                  could receive data.
  445.  *    GEN_INVALID_ARG        - bad bufSize.
  446.  *    FS_WOULD_BLOCK        - no data are available.
  447.  *
  448.  * Side effects:
  449.  *    None.
  450.  *
  451.  *----------------------------------------------------------------------
  452.  */
  453.  
  454. ReturnStatus
  455. Sock_Read(privPtr, bufSize, buffer, amountReadPtr)
  456.     Sock_PrivInfo    *privPtr;    /* Socket to be read from. */
  457.     int            bufSize;    /* Amount to read. */
  458.     Address        buffer;        /* Place to put the data. */
  459.     int            *amountReadPtr;    /* Actual # of bytes stored in buffer.*/
  460. {
  461.     Sock_SharedInfo *sharePtr = privPtr->sharePtr;
  462.     ReturnStatus    status;
  463.  
  464.     stats.sock.read++;
  465.  
  466. #ifndef KERNEL
  467.     if (ips_Debug) {
  468.     (void) fprintf(stderr, "Sock_Read(%d,%d,%x): %d  flags=%x\n",
  469.         privPtr->streamID, privPtr->clientID, privPtr->pid, bufSize,
  470.         privPtr->recvFlags);
  471.     }
  472. #endif
  473.  
  474.     *amountReadPtr = 0;
  475.  
  476.     if (bufSize < 0) {
  477.     return(GEN_INVALID_ARG);
  478.     }
  479.  
  480.     if (sharePtr->error != SUCCESS) {
  481.     status = sharePtr->error;
  482.     sharePtr->error = SUCCESS;
  483.     } else {
  484.     status = protoInfo[sharePtr->protoIndex].ops.read(privPtr, 
  485.                 bufSize, buffer, amountReadPtr);
  486. #ifdef lint
  487.         status = TCP_SocketRead(privPtr, bufSize, buffer, amountReadPtr);
  488.         status = UDP_SocketRead(privPtr, bufSize, buffer, amountReadPtr);
  489.         status = Raw_SocketRead(privPtr, bufSize, buffer, amountReadPtr);
  490. #endif
  491.     }
  492.     if (ips_Debug) {
  493.     (void) fprintf(stderr, "Sock_Read: status %x, amtRead %d\n",
  494.             status, *amountReadPtr);
  495.     }
  496.     return(status);
  497. }
  498.  
  499. /*
  500.  *----------------------------------------------------------------------
  501.  *
  502.  * Sock_Write --
  503.  *
  504.  *    Takes data from the client and causes it to sent out on the network.
  505.  *
  506.  * Results:
  507.  *    SUCCESS            - the operation was successful.
  508.  *    NET_BAD_OPERATION    - the socket was not in a state that could
  509.  *                  could send data.
  510.  *    GEN_INVALID_ARG        - bad bufSize.
  511.  *    FS_WOULD_BLOCK        - no data are available.
  512.  *    
  513.  *
  514.  * Side effects:
  515.  *    A packet will be sent out on the network.
  516.  *
  517.  *----------------------------------------------------------------------
  518.  */
  519.  
  520. ReturnStatus
  521. Sock_Write(privPtr, procID, bufSize, buffer, amtWrittenPtr)
  522.     Sock_PrivInfo    *privPtr;    /* Socket to be written to. */
  523.     Proc_PID        procID;        /* Process performing write. */
  524.     int            bufSize;    /* Size in bytes of buffer. */
  525.     Address        buffer;        /* Data to be sent. */
  526.     int            *amtWrittenPtr;    /* Amount of data actually sent */
  527. {
  528.     ReturnStatus    status;
  529.     Sock_SharedInfo *sharePtr = privPtr->sharePtr;
  530.  
  531.     stats.sock.write++;
  532.  
  533. #ifndef KERNEL
  534.     if (ips_Debug) {
  535.     (void) fprintf(stderr, 
  536.         "Sock_Write(%d,%d,%x): %d  '%.*s'  flags=%x\n", 
  537.         privPtr->streamID, privPtr->clientID, privPtr->pid, 
  538.         bufSize, MIN(25, bufSize), buffer, privPtr->sendInfo.flags);
  539.     }
  540. #endif
  541.  
  542.     if (bufSize < 0) {
  543.     return(GEN_INVALID_ARG);
  544.     }
  545.  
  546.     /*
  547.      * See if we're allowed to send data to the peer. If the socket is 
  548.      * connection-based, it won't be writable if the peer has said to 
  549.      * not send more data.
  550.      */
  551.  
  552.     if (Sock_IsSendStopped(sharePtr)) {
  553. #ifndef KERNEL
  554.     Sig_Send(SIG_PIPE, procID, FALSE);
  555. #endif
  556.     return(FS_BROKEN_PIPE);
  557.     } else if (sharePtr->error != SUCCESS) {
  558.     status = sharePtr->error;
  559.     sharePtr->error = SUCCESS;
  560.     } else if (sharePtr->protoIndex == UDP_PROTO_INDEX) {
  561.     /*
  562.      * Experimental optimized write-path for UDP.  We'll leave the
  563.      * data in the pseudo-device request buffer, set up the
  564.      * packet header there too, and even do fragmenting in
  565.      * place there.
  566.      */
  567.     status = UDP_WriteRequest(privPtr, procID, bufSize, buffer,
  568.                  amtWrittenPtr);
  569.     } else {
  570.     IPS_Packet    packet;
  571.  
  572.     IPS_InitPacket(bufSize, &packet);
  573.     bcopy( buffer, packet.data, bufSize);
  574.     status = protoInfo[sharePtr->protoIndex].ops.write(privPtr, &packet,
  575.                  amtWrittenPtr);
  576. #ifdef lint
  577.     status = TCP_SocketWrite(privPtr, &packet, amtWrittenPtr);
  578.     status = UDP_SocketWrite(privPtr, &packet, amtWrittenPtr);
  579.     status = Raw_SocketWrite(privPtr, &packet, amtWrittenPtr);
  580. #endif
  581.     /*
  582.      * If there's no room to write all of the data, free the packet.
  583.      */
  584.     if (status == FS_WOULD_BLOCK) {
  585.         /*
  586.          * If nothing was written, then free the buffer.
  587.          */
  588.         if (*amtWrittenPtr == 0) {
  589.         free(packet.base);
  590.         }
  591.     }
  592.     }
  593.     if (ips_Debug) {
  594.     (void) fprintf(stderr, "Sock_Write: status %x, amtWritten %d\n",
  595.             status, *amtWrittenPtr);
  596.     }
  597.     return(status);
  598. }
  599.  
  600. /*
  601.  *----------------------------------------------------------------------
  602.  *
  603.  * Sock_IOControl --
  604.  *
  605.  *    Performs various actions based on the command argument.
  606.  *
  607.  * Results:
  608.  *    SUCCESS        - the operation was successful.
  609.  *    other values from the called subroutines.
  610.  *
  611.  * Side effects:
  612.  *    The socket information may be changed.
  613.  *
  614.  *----------------------------------------------------------------------
  615.  */
  616.  
  617. static char *cmdToName[] = {
  618.     "?",
  619.     "LISTEN",
  620.     "ACCEPT_1",
  621.     "ACCEPT_2",
  622.     "GET_LOCAL_ADDR",
  623.     "SET_LOCAL_ADDR",
  624.     "CONNECT",
  625.     "GET_REMOTE_ADDR",
  626.     "GET_OPTION",
  627.     "SET_OPTION",
  628.     "RECV_FLAGS",
  629.     "RECV_FROM",
  630.     "SEND_INFO",
  631.     "SHUTDOWN",
  632.     "SET_PROTOCOL",
  633. };
  634.  
  635. ReturnStatus
  636. Sock_IOControl(privPtr, command, userID, inBufSize, inBuffer, outBufSize,
  637.            outBuffer)
  638.     Sock_PrivInfo    *privPtr;    /* Ptr to socket to do command on. */
  639.     int        command;        /* Command to perform. */
  640.     int     userID;            /* userID of client at time of call */
  641.     int        inBufSize;        /* Size in bytes of inBuffer. */
  642.     Address    inBuffer;        /* Buffer of input data. */
  643.     int        outBufSize;        /* Size in bytes of outBuffer. */
  644.     Address    outBuffer;        /* Buffer to store output data. */
  645. {
  646.     Sock_SharedInfo *sharePtr = privPtr->sharePtr;
  647.     ReturnStatus status;
  648.     int type;
  649.  
  650.     stats.sock.ioctl++;
  651.  
  652.     /*
  653.      * Figure out what type of command it is. If it's a generic command,
  654.      * then let HandleGenericIOC deal with it. If it's a NET command,
  655.      * then we deal with it here.
  656.      */
  657. #ifndef KERNEL
  658.     if (ips_Debug) {
  659.     (void) fprintf(stderr,"Sock_IOC(%d,%d,%x):", 
  660.         privPtr->streamID, privPtr->clientID, privPtr->pid);
  661.     }
  662. #endif
  663.  
  664.     type = command & 0xffff0000;
  665.  
  666.     if (type == 0) {
  667.     return(HandleGenericIOC(privPtr, command, inBufSize, inBuffer,
  668.                 outBufSize, outBuffer));
  669.     } else if (type != IOC_NET) {
  670.     if (ips_Debug) {
  671.         (void) fprintf(stderr,"  INVALID: %x\n", command);
  672.     } else {
  673.         /*
  674.         (void) fprintf(stderr, 
  675.         "Sock_IOControl: invalid ioctl %x on (%d,%d,%x)\n", 
  676.         command, privPtr->streamID, privPtr->clientID, privPtr->pid);
  677.         */
  678.     }
  679.     return(GEN_INVALID_ARG);
  680.     }
  681.  
  682.     if (ips_Debug) {
  683.     (void) fprintf(stderr," %s\n", cmdToName[command & 0xf]);
  684.     }
  685.  
  686.     switch (command) {
  687.  
  688.     /*
  689.      * Convert an active socket into a passive one. The socket will
  690.      * only be able to accept incoming connection requests after 
  691.      * this call.
  692.      *
  693.      * In:   int    backlog;
  694.      */
  695.  
  696.     case IOC_NET_LISTEN:
  697.         if (inBufSize != sizeof(int)) {
  698.         return(GEN_INVALID_ARG);
  699.         }
  700.         if (sharePtr->error != SUCCESS) {
  701.         status = sharePtr->error;
  702.         sharePtr->error = SUCCESS;
  703.         return(status);
  704.         } 
  705. #ifdef lint
  706.         status = TCP_SocketListen(sharePtr, *(int *)inBuffer, 
  707.             userID);
  708. #endif
  709.         return(protoInfo[sharePtr->protoIndex].ops.listen(sharePtr, 
  710.                     *(int *)inBuffer, userID));
  711.         /*NOTREACHED*/
  712.         break;
  713.  
  714.  
  715.     /*
  716.      * For a passive socket, wait for connection request from 
  717.      * any remote host.  This is the first half of acceptance sequence.
  718.      *
  719.      * Out:  ClientData *tokenPtr;
  720.      *       The token is used with the IOC_NET_ACCEPT_CONN_2 ioctl to 
  721.      *     create a new socket for the connection.
  722.      */
  723.  
  724.     case IOC_NET_ACCEPT_CONN_1:
  725.         if (sharePtr->error != SUCCESS) {
  726.         status = sharePtr->error;
  727.         sharePtr->error = SUCCESS;
  728.         return(status);
  729.         } 
  730.         if (outBufSize != sizeof(ClientData)) {
  731.         return(GEN_INVALID_ARG);
  732.         }
  733. #ifdef lint
  734.         status = TCP_SocketAccept(sharePtr, outBuffer);
  735. #endif
  736.         status = protoInfo[sharePtr->protoIndex].ops.accept(sharePtr,
  737.                     outBuffer);
  738.         if ((status == NET_NO_CONNECTS) && 
  739.         (privPtr->fsFlags & FS_NON_BLOCKING)) {
  740.  
  741.         status = FS_WOULD_BLOCK;
  742.         }
  743.         return(status);
  744.         break;
  745.  
  746.  
  747.     /*
  748.      * This ioctl performs the second half of the accept sequence.
  749.      * Given the Sock_SharedInfo token from ACCEPT_CONN_2, it makes the 
  750.      * current sockPtr refer to the socket identified by the token.
  751.      *
  752.      * In: ClientData token;
  753.      * Out: Net_InetSocketAddr *addrPtr;
  754.      */
  755.     case IOC_NET_ACCEPT_CONN_2: {
  756.         Sock_SharedInfo *connSockPtr;
  757.  
  758.         /*
  759.          * We have two sockets now: *sockPtr is a socket that
  760.          * was just created opening the server's pseudo-device.
  761.          * It does not have any of the protocol-dependent information 
  762.          * initialized. *connSockPtr is a socket that was created when
  763.          * a connect request came in. It has the protocol-dependent 
  764.          * info initialized but none of the client-related info. 
  765.          * In this section we merge the 2 sockets into *connSockPtr,
  766.          * then destroy *sockPtr and finally, we cause *connSockPtr 
  767.          * to be used whenever the client uses this socket 
  768.          * pseudo-device.
  769.          */
  770.  
  771.         if (inBufSize != sizeof(ClientData)) {
  772.             return(GEN_INVALID_ARG);
  773.         }
  774.         connSockPtr = (Sock_SharedInfo *) *(ClientData *) inBuffer;
  775.  
  776.         /*
  777.          * Try to validate that the token is really a Sock_SharedInfo 
  778.          * ptr. We're at the mercy of the client to not mangle 
  779.          * the token...
  780.          *
  781.          * To do: stronger validation.
  782.          */
  783.         if ((connSockPtr == (Sock_SharedInfo *) NULL) ||
  784.             (connSockPtr->state != CONNECTED)) {
  785.             return(GEN_INVALID_ARG);
  786.         }
  787.  
  788.         /*
  789.          * Make sure the out buffer (socket address) is 
  790.                  * at least the minimum size.
  791.          */
  792.         if (outBufSize != 0) {
  793.             if (outBufSize < sizeof(Net_InetSocketAddr)) {
  794.             return(GEN_INVALID_ARG);
  795.             }
  796.             connSockPtr->remote.addrFamily = AF_INET;
  797.             * (Net_InetSocketAddr *)outBuffer = connSockPtr->remote;
  798.         }
  799.  
  800.         if (privPtr->sharePtr->clientCount != 1) {
  801.             panic("ACCEPT_2: client count = %d\n",
  802.             privPtr->sharePtr->clientCount);
  803.             return(FAILURE);
  804.         }
  805.  
  806.         /*
  807.          * Transfer the pdev request buffer from the old socket
  808.          * to the new one, so it can be freed properly when the
  809.          * new socket is deleted.
  810.          */
  811.  
  812.         connSockPtr->reqBufSize = privPtr->sharePtr->reqBufSize;
  813.         connSockPtr->requestBuf = privPtr->sharePtr->requestBuf;
  814.         Sock_Destroy(privPtr->sharePtr);
  815.  
  816.         connSockPtr->clientCount = 1;
  817.         List_Insert(&privPtr->links, 
  818.                 LIST_ATREAR(&connSockPtr->clientList));
  819.         privPtr->sharePtr = connSockPtr;
  820.         }
  821.         break;
  822.  
  823.  
  824.  
  825.     /*
  826.      * Get the local <address,port> tuple assigned to the socket.
  827.      */
  828.     case IOC_NET_GET_LOCAL_ADDR:
  829.         /*
  830.          * States above CREATED have the local address.
  831.          */
  832.         if ((int)sharePtr->state <= (int)CREATED) {
  833.         return(FAILURE);
  834.         }
  835.         if (outBufSize < sizeof(Net_InetSocketAddr)) {
  836.         return(GEN_INVALID_ARG);
  837.         }
  838.         sharePtr->local.addrFamily = AF_INET;
  839.         *(Net_InetSocketAddr *)outBuffer = sharePtr->local;
  840.         break;
  841.  
  842.  
  843.     /*
  844.      * Assign the local <address,port> tuple to the socket.
  845.      */
  846.     case IOC_NET_SET_LOCAL_ADDR:
  847.  
  848.         if (inBufSize != sizeof(Net_InetSocketAddr)) {
  849.         return(GEN_INVALID_ARG);
  850.         }
  851.         /*
  852.          * It is an error to bind to an already bound socket.
  853.          */
  854.         if (sharePtr->flags & SOCK_HAVE_BOUND_ADDR) {
  855.         return(GEN_INVALID_ARG);
  856.         }
  857. #ifdef lint
  858.         status = TCP_SocketBind(sharePtr, (Net_InetSocketAddr *)inBuffer,
  859.             userID);
  860.         status = UDP_SocketBind(sharePtr, (Net_InetSocketAddr *)inBuffer,
  861.             userID);
  862.         status = Raw_SocketBind(sharePtr, (Net_InetSocketAddr *)inBuffer,
  863.             userID);
  864. #endif
  865.         status = protoInfo[sharePtr->protoIndex].ops.bind(sharePtr, 
  866.             (Net_InetSocketAddr *)inBuffer, userID);
  867.         if (status == SUCCESS) {
  868.         sharePtr->flags |= SOCK_HAVE_BOUND_ADDR;
  869.         }
  870.         return (status);
  871.         /*NOTREACHED*/
  872.         break;
  873.  
  874.  
  875.     /*
  876.      * Restrict incoming packets to the given remote host.
  877.      * Optionally sets up a virtual circuit to the host.
  878.      */
  879.     case IOC_NET_CONNECT:
  880.         if (inBufSize != sizeof(Net_InetSocketAddr)) {
  881.         return(GEN_INVALID_ARG);
  882.         }
  883.         if (sharePtr->error != SUCCESS) {
  884.         status = sharePtr->error;
  885.         sharePtr->error = SUCCESS;
  886.         return(status);
  887.         } 
  888. #ifdef lint
  889.         status = TCP_SocketConnect(sharePtr, 
  890.             (Net_InetSocketAddr *)inBuffer, TRUE);
  891.         status = UDP_SocketConnect(sharePtr, 
  892.             (Net_InetSocketAddr *)inBuffer, TRUE);
  893.         status = Raw_SocketConnect(sharePtr, 
  894.             (Net_InetSocketAddr *)inBuffer, TRUE);
  895. #endif
  896.         return(protoInfo[sharePtr->protoIndex].ops.connect(sharePtr, 
  897.             (Net_InetSocketAddr *)inBuffer, TRUE));
  898.         /*NOTREACHED*/
  899.         break;
  900.  
  901.  
  902.     /*
  903.      * Get the <address,port> tuple of the remote host for a connected
  904.      * socket.
  905.      */
  906.     case IOC_NET_GET_REMOTE_ADDR:
  907.         if ((int)sharePtr->state < (int)CONNECTED) {
  908.         return(NET_NOT_CONNECTED);
  909.         }
  910.         if (outBufSize < sizeof(Net_InetSocketAddr)) {
  911.         return(GEN_INVALID_ARG);
  912.         }
  913.         sharePtr->remote.addrFamily = AF_INET;
  914.         *(Net_InetSocketAddr *)outBuffer = sharePtr->remote;
  915.         break;
  916.  
  917.  
  918.     /*
  919.      * Get the value of a socket option.
  920.      */
  921.     case IOC_NET_GET_OPTION:
  922.         return(GetOption(sharePtr, inBufSize, inBuffer, outBufSize, 
  923.                 outBuffer));
  924.         /*NOTREACHED*/
  925.         break;
  926.  
  927.  
  928.     /*
  929.      * Set the value of a socket option.
  930.      */
  931.     case IOC_NET_SET_OPTION:
  932.         return(SetOption(sharePtr, inBufSize, inBuffer));
  933.         /*NOTREACHED*/
  934.         break;
  935.  
  936.  
  937.     /*
  938.      * Sets the flags used in the next Sock_Read call.
  939.      */
  940.     case IOC_NET_RECV_FLAGS:
  941.         if (inBufSize != sizeof(privPtr->recvFlags)) {
  942.         return(GEN_INVALID_ARG);
  943.         }
  944.         privPtr->recvFlags = *(int *) inBuffer;
  945.         break;
  946.  
  947.  
  948.     /*
  949.      * Returns the <address, port> tuple of the most recently received  
  950.      * packet.
  951.      */
  952.     case IOC_NET_RECV_FROM:
  953.         if (sharePtr->error != SUCCESS) {
  954.         status = sharePtr->error;
  955.         sharePtr->error = SUCCESS;
  956.         return(status);
  957.         } else if (outBufSize != sizeof(privPtr->recvFrom)) {
  958.         return(GEN_INVALID_ARG);
  959.         }
  960.         privPtr->recvFrom.addrFamily = AF_INET;
  961.         *(Net_InetSocketAddr *)outBuffer = privPtr->recvFrom;
  962.         break;
  963.  
  964.  
  965.     /*
  966.      * Sets the flag and the remote address for the next Sock_Write call.
  967.      */
  968.     case IOC_NET_SEND_INFO:
  969.         if (inBufSize != sizeof(privPtr->sendInfo)) {
  970.         return(GEN_INVALID_ARG);
  971.         } 
  972.         privPtr->sendInfo = *(Net_SendInfo *) inBuffer;
  973.         privPtr->sendInfoValid = TRUE;
  974.         break;
  975.  
  976.  
  977.     /*
  978.      * Causes the socket to be closed down.
  979.      */
  980.     case IOC_NET_SHUTDOWN:
  981.         if (inBufSize != sizeof(int)) {
  982.         return(GEN_INVALID_ARG);
  983.         }
  984. #ifdef lint
  985.             status = TCP_SocketShutdown(sharePtr, *(int *)inBuffer);
  986.             status = UDP_SocketShutdown(sharePtr, *(int *)inBuffer);
  987.             status = Raw_SocketShutdown(sharePtr, *(int *)inBuffer);
  988. #endif
  989.         return(protoInfo[sharePtr->protoIndex].ops.shutdown(sharePtr, 
  990.                 *(int *)inBuffer));
  991.         /*NOTREACHED*/
  992.         break;
  993.  
  994.  
  995.     /*
  996.      * Specify a protocol to be used by the socket.
  997.      */
  998.     case IOC_NET_SET_PROTOCOL:
  999.         if (inBufSize != sizeof(sharePtr->protocol)) {
  1000.         return(GEN_INVALID_ARG);
  1001.         } 
  1002.         sharePtr->protocol = *(int *)inBuffer;
  1003.         break;
  1004.  
  1005.     /*
  1006.      * Return a flag to indicate if out-of-band data will be
  1007.      * read at the next read call.
  1008.      */
  1009.     case IOC_NET_IS_OOB_DATA_NEXT:
  1010.         if (outBufSize != sizeof(int)) {
  1011.         return(GEN_INVALID_ARG);
  1012.         } 
  1013.         *(int *)outBuffer = (sharePtr->flags & SOCK_URGENT_DATA_NEXT) != 0;
  1014.         break;
  1015.  
  1016.     case IOC_NET_STATS:
  1017.         if (inBufSize != sizeof(int)) {
  1018.         return(GEN_INVALID_ARG);
  1019.         }
  1020.         Stat_Command(*(unsigned int *)inBuffer);
  1021.         break;
  1022.  
  1023.     default:
  1024.         (void) fprintf(stderr, "Warning: Sock_IOControl: unknown command %x\n",
  1025.             command);
  1026.         break;
  1027.     }
  1028.     return(SUCCESS);
  1029. }
  1030.  
  1031.  
  1032. /*
  1033.  *----------------------------------------------------------------------
  1034.  *
  1035.  * HandleGenericIOC --
  1036.  *
  1037.  *    Handles generic I/O controls.
  1038.  *
  1039.  * Results:
  1040.  *    SUCCESS        - the operation was successful.
  1041.  *    GEN_INVALID_ARG    - the in or out buffer size was wrong.
  1042.  *
  1043.  * Side effects:
  1044.  *    Socket state may be updated.
  1045.  *
  1046.  *----------------------------------------------------------------------
  1047.  */
  1048. static char *genericCommands[] = {
  1049.     "???",
  1050.     "REPOSITION",
  1051.     "GET_FLAGS",
  1052.     "SET_FLAGS",
  1053.     "SET_BITS",
  1054.     "CLEAR_BITS",
  1055.     "TRUNCATE",
  1056.     "LOCK",
  1057.     "UNLOCK",
  1058.     "NUM_READABLE",
  1059.     "GET_OWNER",
  1060.     "SET_OWNER",
  1061.     "MAP",
  1062. };
  1063.  
  1064. static ReturnStatus
  1065. HandleGenericIOC(privPtr, command, inBufSize, inBuffer, outBufSize, outBuffer)
  1066.     register Sock_PrivInfo *privPtr;    /* Socket to perform command on. */
  1067.     int        command;        /* Command to perform. */
  1068.     int        inBufSize;        /* Size in bytes of inBuffer. */
  1069.     Address    inBuffer;        /* Buffer of input data. */
  1070.     int        outBufSize;        /* Size in bytes of outBuffer. */
  1071.     Address    outBuffer;        /* Buffer to store output data. */
  1072. {
  1073.     int        flags;
  1074.  
  1075.     if (ips_Debug) {
  1076.     (void) fprintf(stderr,"  generic: %s\n", genericCommands[command]);
  1077.     }
  1078.  
  1079.     switch (command) {
  1080.     case IOC_GET_FLAGS:
  1081.         if (outBufSize != sizeof(flags)) {
  1082.         return(GEN_INVALID_ARG);
  1083.         }
  1084.         *(int *)outBuffer = 0;
  1085.         break;
  1086.         
  1087.     case IOC_SET_FLAGS:
  1088.     case IOC_SET_BITS:
  1089.         if (inBufSize != sizeof(flags)) {
  1090.         return(GEN_INVALID_ARG);
  1091.         }
  1092.         flags = *(int *)inBuffer;
  1093.         if (flags & IOC_NON_BLOCKING) {
  1094.         privPtr->fsFlags |= FS_NON_BLOCKING;
  1095.         }
  1096.         break;
  1097.  
  1098.     case IOC_CLEAR_BITS:
  1099.         if (inBufSize != sizeof(flags)) {
  1100.         return(GEN_INVALID_ARG);
  1101.         }
  1102.         flags = *(int *)inBuffer;
  1103.         if (flags & IOC_NON_BLOCKING) {
  1104.         privPtr->fsFlags &= ~FS_NON_BLOCKING;
  1105.         }
  1106.         break;
  1107.  
  1108.     case IOC_GET_OWNER:
  1109.         if (outBufSize != sizeof(privPtr->sharePtr->owner)) {
  1110.         return(GEN_INVALID_ARG);
  1111.         }
  1112.         *(Ioc_Owner *)outBuffer = privPtr->sharePtr->owner;
  1113.         break;
  1114.  
  1115.     case IOC_SET_OWNER:
  1116.         if (inBufSize != sizeof(privPtr->sharePtr->owner)) {
  1117.         return(GEN_INVALID_ARG);
  1118.         }
  1119.         privPtr->sharePtr->owner = *(Ioc_Owner *)inBuffer;
  1120.         break;
  1121.  
  1122.     case IOC_NUM_READABLE:
  1123.         if (outBufSize != sizeof(int)) {
  1124.         return(GEN_INVALID_ARG);
  1125.         }
  1126.         *(int *)outBuffer = Sock_BufSize(privPtr->sharePtr, SOCK_RECV_BUF,
  1127.                         SOCK_BUF_USED);
  1128.         break;
  1129.     default:
  1130.         break;
  1131.     }
  1132.     return(SUCCESS);
  1133. }
  1134.  
  1135.  
  1136. /*
  1137.  *----------------------------------------------------------------------
  1138.  *
  1139.  * GetOption --
  1140.  *
  1141.  *    Handles the IOC_NET_GET_OPTION I/O control.
  1142.  *
  1143.  * Results:
  1144.  *    SUCCESS        - the operation was successful.
  1145.  *    GEN_INVALID_ARG    - the in or out buffer size was wrong.
  1146.  *
  1147.  * Side effects:
  1148.  *    None.
  1149.  *
  1150.  *----------------------------------------------------------------------
  1151.  */
  1152.  
  1153. static ReturnStatus
  1154. GetOption(sockPtr, inBufSize, inBuffer, outBufSize, outBuffer)
  1155.     register Sock_SharedInfo *sockPtr;    /* Socket to perform command on. */
  1156.     int        inBufSize;        /* Size in bytes of inBuffer. */
  1157.     Address    inBuffer;        /* Buffer of input data. */
  1158.     int        outBufSize;        /* Size in bytes of outBuffer. */
  1159.     Address    outBuffer;        /* Buffer to store output data. */
  1160. {
  1161.     int level;
  1162.     int optName;
  1163.  
  1164.     if (inBufSize != 2 * sizeof(int)) {
  1165.     return(GEN_INVALID_ARG);
  1166.     }
  1167.     level = ((int *)inBuffer)[0];
  1168.     optName = ((int *)inBuffer)[1];
  1169.  
  1170.  
  1171.     /*
  1172.      * See if the option is for the socket or a protocol.
  1173.      */
  1174.     if (level != NET_OPT_LEVEL_SOCKET) {
  1175.     int protoIndex;
  1176.  
  1177.     switch (level) {
  1178.         case NET_IP_PROTOCOL_IP:
  1179.         protoIndex = RAW_PROTO_INDEX;
  1180.         break;
  1181.  
  1182.         case NET_IP_PROTOCOL_TCP:
  1183.         protoIndex = TCP_PROTO_INDEX;
  1184.         break;
  1185.  
  1186.         case NET_IP_PROTOCOL_UDP:
  1187.         protoIndex = UDP_PROTO_INDEX;
  1188.         break;
  1189.  
  1190.         default:
  1191.         return(GEN_INVALID_ARG);
  1192.         break;
  1193.     }
  1194.     return(protoInfo[protoIndex].ops.getOption(sockPtr, 
  1195.             optName, outBufSize, outBuffer));
  1196.     } else {
  1197.  
  1198.     /*
  1199.      * We want to return at least  4 bytes of data.
  1200.      */
  1201.     if (outBufSize < sizeof(int)) {
  1202.         return(GEN_INVALID_ARG);
  1203.     }
  1204.  
  1205.     switch (optName) {
  1206.         case NET_OPT_DEBUG:
  1207.         case NET_OPT_REUSE_ADDR:
  1208.         case NET_OPT_KEEP_ALIVE:
  1209.         case NET_OPT_DONT_ROUTE:
  1210.         case NET_OPT_BROADCAST:
  1211.         case NET_OPT_USE_LOOPBACK:
  1212.         case NET_OPT_OOB_INLINE:
  1213.         *(Boolean *)outBuffer = sockPtr->options & optName;
  1214.         break;
  1215.  
  1216.         case NET_OPT_LINGER: {
  1217.             Net_LingerInfo linger;
  1218.  
  1219.             if (outBufSize != sizeof(linger)) {
  1220.             return(GEN_INVALID_ARG);
  1221.             }
  1222.  
  1223.             linger.onOff = sockPtr->options & NET_OPT_LINGER;
  1224.             linger.linger = sockPtr->linger;
  1225.             *(Net_LingerInfo *)outBuffer = linger;
  1226.         }
  1227.         break;
  1228.  
  1229.         case NET_OPT_SEND_BUF_SIZE:
  1230.         *(int *)outBuffer = Sock_BufSize(sockPtr, SOCK_SEND_BUF, 
  1231.                     SOCK_BUF_MAX_SIZE);
  1232.         break;
  1233.  
  1234.         case NET_OPT_RECV_BUF_SIZE:
  1235.         *(int *)outBuffer = Sock_BufSize(sockPtr, SOCK_RECV_BUF, 
  1236.                     SOCK_BUF_MAX_SIZE);
  1237.         break;
  1238.  
  1239.         case NET_OPT_SEND_LOWAT:
  1240.         *(int *)outBuffer = 0;
  1241.                 /* Sock_BufSize(sockPtr, SOCK_SEND_BUF, 
  1242.                     SOCK_BUF_MIN_USED); */
  1243.         break;
  1244.  
  1245.         case NET_OPT_RECV_LOWAT:
  1246.         *(int *)outBuffer = 0;
  1247.                 /* Sock_BufSize(sockPtr, SOCK_RECV_BUF, 
  1248.                     SOCK_BUF_MIN_USED); */
  1249.         break;
  1250.  
  1251.         case NET_OPT_SEND_TIMEOUT:
  1252.         *(int *)outBuffer = 0;
  1253.         break;
  1254.  
  1255.         case NET_OPT_RECV_TIMEOUT:
  1256.         *(int *)outBuffer = 0;
  1257.         break;
  1258.  
  1259.         case NET_OPT_ERROR:
  1260.         *(int *)outBuffer = sockPtr->error;
  1261.         sockPtr->error = SUCCESS;
  1262.         break;
  1263.  
  1264.         case NET_OPT_TYPE:
  1265.         *(int *)outBuffer = 0;
  1266.         break;
  1267.  
  1268.  
  1269.         default:
  1270.         return(GEN_INVALID_ARG);
  1271.         break;
  1272.     }
  1273.     }
  1274.     return(SUCCESS);
  1275. }
  1276.  
  1277.  
  1278. /*
  1279.  *----------------------------------------------------------------------
  1280.  *
  1281.  * SetOption --
  1282.  *
  1283.  *    Handles the IOC_NET_SET_OPTION I/O control.
  1284.  *
  1285.  * Results:
  1286.  *    SUCCESS        - the operation was successful.
  1287.  *    GEN_INVALID_ARG    - the in buffer size was wrong.
  1288.  *
  1289.  * Side effects:
  1290.  *    Socket state is updated.
  1291.  *
  1292.  *----------------------------------------------------------------------
  1293.  */
  1294.  
  1295. static ReturnStatus
  1296. SetOption(sockPtr, inBufSize, inBuffer)
  1297.     register Sock_SharedInfo *sockPtr;    /* Socket to perform command on. */
  1298.     int        inBufSize;        /* Size in bytes of inBuffer. */
  1299.     Address    inBuffer;        /* Buffer of input data. */
  1300. {
  1301.     int level;
  1302.     int optName;
  1303.  
  1304.     /*
  1305.      * The input buffer has the following format:
  1306.      *  first 4 bytes:    level
  1307.      *  second 4 bytes:    option name
  1308.      *  rest:          option data
  1309.      *
  1310.      * The option name implies the size of the option data.
  1311.      */
  1312.  
  1313.     if (inBufSize <= 2 * sizeof(int)) {
  1314.     return(GEN_INVALID_ARG);
  1315.     }
  1316.     level = ((int *)inBuffer)[0];
  1317.     optName = ((int *)inBuffer)[1];
  1318.  
  1319.     inBuffer  += 2 * sizeof(int);
  1320.     inBufSize -= 2 * sizeof(int);
  1321.  
  1322.     if (level != NET_OPT_LEVEL_SOCKET) {
  1323.     int protoIndex;
  1324.  
  1325.     switch (level) {
  1326.         case NET_IP_PROTOCOL_IP:
  1327.         protoIndex = RAW_PROTO_INDEX;
  1328.         break;
  1329.  
  1330.         case NET_IP_PROTOCOL_TCP:
  1331.         protoIndex = TCP_PROTO_INDEX;
  1332.         break;
  1333.  
  1334.         case NET_IP_PROTOCOL_UDP:
  1335.         protoIndex = UDP_PROTO_INDEX;
  1336.         break;
  1337.  
  1338.         default:
  1339.         return(GEN_INVALID_ARG);
  1340.         break;
  1341.     }
  1342.     return(protoInfo[protoIndex].ops.setOption(sockPtr, 
  1343.             optName, inBufSize, inBuffer));
  1344.     } else {
  1345.  
  1346.     if (inBufSize < sizeof(int)) {
  1347.         return(GEN_INVALID_ARG);
  1348.     }
  1349.  
  1350.     switch (optName) {
  1351.         case NET_OPT_DEBUG:
  1352.         break;
  1353.         case NET_OPT_REUSE_ADDR:
  1354.         case NET_OPT_KEEP_ALIVE:
  1355.         case NET_OPT_DONT_ROUTE:
  1356.         case NET_OPT_BROADCAST:
  1357.         case NET_OPT_USE_LOOPBACK:
  1358.         case NET_OPT_OOB_INLINE:
  1359.         if (*(Boolean *)inBuffer) {
  1360.             sockPtr->options |= optName;
  1361.         } else {
  1362.             sockPtr->options &= ~optName;
  1363.         }
  1364.         break;
  1365.  
  1366.         case NET_OPT_LINGER: 
  1367.         if (inBufSize != sizeof(Net_LingerInfo)) {
  1368.             return(GEN_INVALID_ARG);
  1369.         }
  1370.  
  1371.         if (((Net_LingerInfo *)inBuffer)->onOff) {
  1372.             sockPtr->options |= optName;
  1373.         } else {
  1374.             sockPtr->options &= ~optName;
  1375.         }
  1376.         sockPtr->linger = ((Net_LingerInfo *)inBuffer)->linger;
  1377.         if (sockPtr->linger > SOCK_MAX_LINGER_TIME) {
  1378.             sockPtr->linger = SOCK_MAX_LINGER_TIME;
  1379.         }
  1380.         break;
  1381.  
  1382.         /*
  1383.          * To do: implement the following options.
  1384.          */
  1385.         case NET_OPT_SEND_BUF_SIZE:
  1386.         break;
  1387.  
  1388.         case NET_OPT_RECV_BUF_SIZE:
  1389.         break;
  1390.  
  1391.         case NET_OPT_SEND_LOWAT:
  1392.         break;
  1393.  
  1394.         case NET_OPT_RECV_LOWAT:
  1395.         break;
  1396.  
  1397.         case NET_OPT_SEND_TIMEOUT:
  1398.         break;
  1399.  
  1400.         case NET_OPT_RECV_TIMEOUT:
  1401.         break;
  1402.  
  1403.         default:
  1404.         return(GEN_INVALID_ARG);
  1405.         break;
  1406.     }
  1407.     }
  1408.     return(SUCCESS);
  1409. }
  1410.  
  1411.  
  1412. /*
  1413.  *----------------------------------------------------------------------
  1414.  *
  1415.  * Sock_Select --
  1416.  *
  1417.  *    Handles a select request from the client. The protocol-dependent
  1418.  *    select routine does the real work of checking if the socket is
  1419.  *    readable, writable or has an exception condition.
  1420.  *
  1421.  * Results:
  1422.  *    The state of the select bits.
  1423.  *
  1424.  * Side effects:
  1425.  *    None.
  1426.  *
  1427.  *----------------------------------------------------------------------
  1428.  */
  1429.  
  1430. int
  1431. Sock_Select(ptr, isPrivPointer)
  1432.     ClientData        ptr;        /* Sock_SharedInfo or PrivInfo ptr. */
  1433.     Boolean        isPrivPointer;    /* If TRUE, ptr is really a privPtr
  1434.                      * otherwise it's a sharePtr. */
  1435. {
  1436.     int flags = 0;
  1437.     Sock_SharedInfo *sharePtr;
  1438.  
  1439.     if (isPrivPointer) {
  1440.     sharePtr = ((Sock_PrivInfo *) ptr)->sharePtr;
  1441.     } else {
  1442.     sharePtr = (Sock_SharedInfo *) ptr;
  1443.     }
  1444.  
  1445.     stats.sock.select++;
  1446.  
  1447.     if (sharePtr->error != SUCCESS) {
  1448.     /*
  1449.      * If there's an error, waiting to be discovered, lie and tell
  1450.      * the client that what he wants is ready so he'll attempt the
  1451.      * operation and then find the error.
  1452.      */
  1453.     return(FS_READABLE|FS_WRITABLE|FS_EXCEPTION);
  1454.     }
  1455.  
  1456. #ifdef lint
  1457.     flags = TCP_SocketSelect(sharePtr);
  1458.     flags = UDP_SocketSelect(sharePtr);
  1459.     flags = Raw_SocketSelect(sharePtr);
  1460. #endif
  1461.     flags = protoInfo[sharePtr->protoIndex].ops.select(sharePtr);
  1462.  
  1463.     if (ips_Debug) {
  1464.     (void) fprintf(stderr, "Sock_Select: out = %c%c%c\n", 
  1465.         (flags & FS_READABLE)  ? 'R': '-',
  1466.         (flags & FS_WRITABLE)  ? 'W': '-',
  1467.         (flags & FS_EXCEPTION) ? 'E': '-');
  1468.     }
  1469.     return(flags);
  1470. }
  1471.  
  1472.  
  1473. /*
  1474.  *----------------------------------------------------------------------
  1475.  *
  1476.  * Sock_NotifyWaiter --
  1477.  *
  1478.  *    Issues an I/O control to tell the kernel that the select state
  1479.  *    of socket has changed.
  1480.  *
  1481.  * Results:
  1482.  *    None.
  1483.  *
  1484.  * Side effects:
  1485.  *    The kernel's notion of the socket select state is changed.
  1486.  *
  1487.  *----------------------------------------------------------------------
  1488.  */
  1489.  
  1490. void
  1491. Sock_NotifyWaiter(sharePtr, flags)
  1492.     Sock_SharedInfo    *sharePtr;    /* This socket has new select state. */
  1493.     int            flags;        /* ignored. */
  1494. {
  1495. #ifndef KERNEL
  1496.     ReturnStatus status;
  1497.     register Sock_PrivInfo    *privPtr;
  1498.  
  1499.     int selectBits;
  1500.  
  1501.     if (ips_Debug) {
  1502.     (void) fprintf(stderr, "Sock_NotifyWaiter:  %c%c%c\n",
  1503.         (flags & FS_READABLE)  ? 'R': '-',
  1504.         (flags & FS_WRITABLE)  ? 'W': '-',
  1505.         (flags & FS_EXCEPTION) ? 'E': '-');
  1506.     }
  1507.  
  1508.     /*
  1509.      * Use the OR'd combination of flags and Sock_Select because the
  1510.      * caller might want to indicate that something's ready that
  1511.      * isn't returned by the select routine. This is subject to race
  1512.      * conditions so the caller be prepared.
  1513.      */
  1514.     selectBits = flags | Sock_Select((ClientData) sharePtr, FALSE);
  1515.  
  1516.     /*
  1517.      * Go thought the list of clients and tell the kernel that 
  1518.      * the select flags have changed.
  1519.      */
  1520.  
  1521.     LIST_FORALL(&sharePtr->clientList, (List_Links *)privPtr) {
  1522.     if (ips_Debug) {
  1523.         (void) fprintf(stderr, "\tnotifying (%d,%d,%x)\n",
  1524.         privPtr->streamID, privPtr->clientID, privPtr->pid);
  1525.     }
  1526.  
  1527.     status = Fs_IOControl(privPtr->streamID, IOC_PDEV_READY, 
  1528.             sizeof(int), (Address) &selectBits, 0, (Address) NULL);
  1529.  
  1530.     if (status != SUCCESS) {
  1531.         Stat_PrintMsg(status, "Sock_NotifyWaiter: PDEV_READY ioctl");
  1532.     }
  1533.     }
  1534. #else
  1535.     /*
  1536.      * KERNEL code.
  1537.      */
  1538.     register FsSocketIOHandle *sockHandlePtr;
  1539.     register Sock_PrivInfo *privPtr;
  1540.  
  1541.     flags |= Sock_Select((ClientData)sharePtr, FALSE);
  1542.  
  1543.     LIST_FORALL(&sharePtr->clientList, (List_Links *)privPtr) {
  1544.     sockHandlePtr = privPtr->sockHandlePtr;
  1545.     if (flags & FS_READABLE) {
  1546.         FsWaitListNotify(&sockHandlePtr->readWaitList);
  1547.     }
  1548.     if (flags & FS_WRITABLE) {
  1549.         FsWaitListNotify(&sockHandlePtr->writeWaitList);
  1550.     }
  1551.     if (flags & FS_EXCEPTABLE) {
  1552.         FsWaitListNotify(&sockHandlePtr->exceptWaitList);
  1553.     }
  1554.     }
  1555. #endif
  1556. }
  1557.  
  1558.  
  1559. /*
  1560.  *----------------------------------------------------------------------
  1561.  *
  1562.  * Sock_Match --
  1563.  *
  1564.  *    Searchs the list of sockets for a protocol to see if any of
  1565.  *    them have the same <address,port> tuple for the given source and
  1566.  *    destination tuples. This routine is used by the protocol-dependent
  1567.  *    input procedures whenever a packet arrives in order to find the socket 
  1568.  *    information necessary to handle the packet.
  1569.  *
  1570.  * Results:
  1571.  *    A pointer to the socket info that matches the addresses.
  1572.  *
  1573.  * Side effects:
  1574.  *    None.
  1575.  *
  1576.  *----------------------------------------------------------------------
  1577.  */
  1578.  
  1579. Sock_SharedInfo *
  1580. Sock_Match(protIndex, localAddr, localPort, remoteAddr, remotePort,
  1581.     wildcardSearchWanted)
  1582.     int            protIndex;    /* Type of socket to look at. */
  1583.     Net_InetAddress    localAddr;    /* Local IP address to match. */
  1584.     unsigned int    localPort;    /* Local port address to match. */
  1585.     Net_InetAddress    remoteAddr;    /* Remote IP address to match. */
  1586.     unsigned int    remotePort;    /* Remote port address to match. */
  1587.     Boolean        wildcardSearchWanted;    /* If TRUE, allow wildcard
  1588.                          * matches. */
  1589. {
  1590.     register Sock_SharedInfo    *sockPtr;
  1591.     Sock_SharedInfo    *wildPtr = (Sock_SharedInfo *) NULL;
  1592.  
  1593.     int numWildcardMatches;
  1594.     int prevNumWildcardMatches = 3;
  1595.  
  1596.     /*
  1597.      * Search the list of sockets for the given protocol and try
  1598.      * to match the local and remote <address,port> tuples to the
  1599.      * ones in the socket. The addresses my be a wildcard value, that
  1600.      * is, a value that matches any address. If wildcarding is allowed,
  1601.      * try to find the socket with the highest number of exact matches.
  1602.      * If wildcarding is not allowed, then find the socket that has exact
  1603.      * matches.
  1604.      */
  1605.  
  1606.     LIST_FORALL(&protoInfo[protIndex].list, (List_Links *) sockPtr){
  1607.     if (sockPtr->protoIndex != protIndex) {
  1608.         panic("Sock_Match: bad protocol %d\n", 
  1609.                 sockPtr->protoIndex);
  1610.     }
  1611.  
  1612.     /*
  1613.      * The local ports must always match.
  1614.      */
  1615.     if (localPort != sockPtr->local.port) {
  1616.         continue;
  1617.     }
  1618.  
  1619.     numWildcardMatches = 0;
  1620.     if (sockPtr->local.address != localAddr) {
  1621.         /*
  1622.          * If they don't match, see if one of them is a wildcard.
  1623.          */
  1624.         if ((sockPtr->local.address == 
  1625.         Net_HostToNetInt(NET_INET_ANY_ADDR)) ||
  1626.         (localAddr == Net_HostToNetInt(NET_INET_ANY_ADDR))) {
  1627.  
  1628.         numWildcardMatches += 1;
  1629.         } else {
  1630.         /*
  1631.          * Neither's a wildcard, so go on to the next socket.
  1632.          */
  1633.         continue;
  1634.         }
  1635.     } /* else {
  1636.        *   The addresses match. They are real or wildcard addresses.
  1637.        * }
  1638.        *
  1639.        */
  1640.  
  1641.     if (sockPtr->remote.address != remoteAddr ||
  1642.         remoteAddr == Net_HostToNetInt(NET_INET_ANY_ADDR)) {
  1643.         /*
  1644.          * If they don't match or the remoteAddr is a wildcard (this is
  1645.          * only used by the ds3100's when they boot), see if one of them 
  1646.          * is a wildcard.
  1647.          */
  1648.         if ((sockPtr->remote.address == Net_HostToNetInt(NET_INET_ANY_ADDR)) ||
  1649.         (remoteAddr == Net_HostToNetInt(NET_INET_ANY_ADDR))) {
  1650.  
  1651.         numWildcardMatches += 1;
  1652.         } else {
  1653.         /*
  1654.          * Neither's a wildcard, so go on to the next socket.
  1655.          */
  1656.         continue;
  1657.         }
  1658.     } else {
  1659.         /*
  1660.          * The addresses match but make sure the port numbers match, too.
  1661.          */
  1662.         if (sockPtr->remote.port != remotePort) {
  1663.         continue;
  1664.         }
  1665.     }
  1666.  
  1667.     if (numWildcardMatches == 0) {
  1668.         /*
  1669.          * Got an exact match!
  1670.          */
  1671.  
  1672.         return((Sock_SharedInfo *) sockPtr);
  1673.  
  1674.     } else if (!wildcardSearchWanted) {
  1675.  
  1676.         /*
  1677.          * We want an exact match but there was at least 1 wild card
  1678.          * match, so go on to the next socket.
  1679.          */
  1680.         continue;
  1681.  
  1682.     } else if (numWildcardMatches < prevNumWildcardMatches) {
  1683.         /*
  1684.          * Got a wildcard match, but see if the other sockets
  1685.          * are an exact match or have a smaller number of wildcard
  1686.          * matches.
  1687.          */
  1688.  
  1689.         wildPtr = sockPtr;
  1690.         prevNumWildcardMatches = numWildcardMatches;
  1691.     }
  1692.     }
  1693.     return((Sock_SharedInfo *) wildPtr);
  1694. }
  1695.  
  1696.  
  1697. /*
  1698.  *----------------------------------------------------------------------
  1699.  *
  1700.  * Sock_ReturnError --
  1701.  *
  1702.  *    Notifies sockets communicating with the given destination that 
  1703.  *    an error has occured. Called by the ICMP layer when it receives
  1704.  *    an error packet.
  1705.  *
  1706.  * Results:
  1707.  *    None.
  1708.  *
  1709.  * Side effects:
  1710.  *    An error status is saved in the socket info struct and the
  1711.  *    client is notified so it if was waiting, it can find out
  1712.  *    about the problem.
  1713.  *
  1714.  *----------------------------------------------------------------------
  1715.  */
  1716.  
  1717. void
  1718. Sock_ReturnError(status, protocol, destAddr, dataPtr)
  1719.     ReturnStatus    status;        /* Error status to be saved. */
  1720.     int            protocol;    /* Look at all sockets of this 
  1721.                      * protocol. */
  1722.     Net_InetAddress    destAddr;    /* Address that caused the error. */
  1723.     Address         dataPtr;    /* Protocol-dependent value. */
  1724. {
  1725.     register Sock_SharedInfo    *sockPtr;
  1726.     int    destPort = 0;
  1727.  
  1728.     /*
  1729.      * Convert the official IP protocol numbers into its corresponding
  1730.      * internal number.
  1731.      */
  1732.     switch (protocol) {
  1733.     case NET_IP_PROTOCOL_IP:
  1734.         protocol = RAW_PROTO_INDEX;
  1735.         break;
  1736.  
  1737.     case NET_IP_PROTOCOL_TCP:
  1738.         protocol = TCP_PROTO_INDEX;
  1739.         destPort = ((Net_UDPHeader *)dataPtr)->destPort;
  1740.         break;
  1741.  
  1742.     case NET_IP_PROTOCOL_UDP:
  1743.         protocol = UDP_PROTO_INDEX;
  1744.         destPort = ((Net_TCPHeader *)dataPtr)->destPort;
  1745.         break;
  1746.  
  1747.     default:
  1748.         (void) fprintf(stderr, "Warning: Sock_ReturnError: bad protocol %d\n",
  1749.             protocol);
  1750.         return;
  1751.     }
  1752.  
  1753.     /*
  1754.      * Look at every socket for this protocol to see if the socket has
  1755.      * dealt with error-producing address. If a socket is connected, it's
  1756.      * easy to determine this.  There's only 1 remote address that the
  1757.      * socket deals with and its address is available.  If a socket isn't
  1758.      * connected, it can communicate will many hosts. Only the last
  1759.      * destination address is saved so if the socket sends many packets to
  1760.      * several addresses before the error comes in, the error value will
  1761.      * be missed.
  1762.      */
  1763.     LIST_FORALL(&protoInfo[protocol].list, (List_Links *) sockPtr) {
  1764.     if ((int)sockPtr->state >= (int)CONNECTED) {
  1765.         if (sockPtr->remote.address == destAddr) {
  1766.         sockPtr->error = status;
  1767.         Sock_NotifyWaiter(sockPtr,FS_READABLE|FS_WRITABLE|FS_EXCEPTION);
  1768.         }
  1769.     } else {
  1770.         if ((sockPtr->sentTo.port == destPort)  &&
  1771.         (sockPtr->sentTo.address == destAddr)) {
  1772.         sockPtr->error = status;
  1773.         Sock_NotifyWaiter(sockPtr,FS_READABLE|FS_WRITABLE|FS_EXCEPTION);
  1774.         }
  1775.     }
  1776.     }
  1777. }
  1778.  
  1779.  
  1780. /*
  1781.  *----------------------------------------------------------------------
  1782.  *
  1783.  * Sock_Clone --
  1784.  *
  1785.  *    Creates a new socket and copies the state information from
  1786.  *    an existing socket. Called by a protocol-dependent routine
  1787.  *    to duplicate a passive socket.
  1788.  *
  1789.  * Results:
  1790.  *    None.
  1791.  *
  1792.  * Side effects:
  1793.  *    Memory for the new socket info struct is allocated.
  1794.  *
  1795.  *----------------------------------------------------------------------
  1796.  */
  1797.  
  1798. Sock_SharedInfo *
  1799. Sock_Clone(sockPtr, attachParent)
  1800.     Sock_SharedInfo    *sockPtr;    /* Socket to be cloned. */
  1801.     Boolean        attachParent;    /* If TRUE, save a ptr to the parent. */
  1802. {
  1803.     Sock_SharedInfo *newSockPtr;
  1804.  
  1805.     newSockPtr = (Sock_SharedInfo *) malloc(sizeof(Sock_SharedInfo));
  1806.     bzero((Address) newSockPtr, sizeof(Sock_SharedInfo));
  1807.  
  1808.     *newSockPtr = *sockPtr;
  1809.     newSockPtr->reqBufSize    = 0;
  1810.     newSockPtr->requestBuf    = 0;
  1811.     newSockPtr->state        = CREATED;
  1812.     newSockPtr->clientCount    = 0;
  1813.     newSockPtr->local.port    = 0;
  1814.     newSockPtr->local.address    = Net_HostToNetInt(NET_INET_ANY_ADDR);
  1815.     newSockPtr->remote.port    = 0;
  1816.     newSockPtr->remote.address    = Net_HostToNetInt(NET_INET_ANY_ADDR);
  1817.     newSockPtr->protoData    = (ClientData) NULL;
  1818.     if (attachParent) {
  1819.     newSockPtr->parentPtr = sockPtr;
  1820.     }
  1821.  
  1822.     List_Init(&newSockPtr->clientList);
  1823.     List_InitElement(&newSockPtr->protoLinks);
  1824.     List_Insert(&newSockPtr->protoLinks,
  1825.             LIST_ATREAR(&protoInfo[sockPtr->protoIndex].list));
  1826.  
  1827.     return(newSockPtr);
  1828. }
  1829.  
  1830.  
  1831. /*
  1832.  *----------------------------------------------------------------------
  1833.  *
  1834.  * Sock_Destroy --
  1835.  *
  1836.  *    Frees all memory allocated to a Sock_SharedInfo struct.
  1837.  *    The protocol-dependent routine is called to destroy
  1838.  *    protocol data first.
  1839.  *
  1840.  *    The sockPtr should not be used after this routine completes.
  1841.  *
  1842.  * Results:
  1843.  *    None.
  1844.  *
  1845.  * Side effects:
  1846.  *    Memory is freed.
  1847.  *
  1848.  *----------------------------------------------------------------------
  1849.  */
  1850.  
  1851. void
  1852. Sock_Destroy(sockPtr)
  1853.     Sock_SharedInfo *sockPtr;        /* Socket to be destroyed. */
  1854. {
  1855.     protoInfo[sockPtr->protoIndex].ops.destroy(sockPtr->protoData);
  1856.     List_Remove(&sockPtr->protoLinks);
  1857.     Sock_BufRemove(sockPtr, SOCK_RECV_BUF, -1);
  1858.     Sock_BufRemove(sockPtr, SOCK_SEND_BUF, -1);
  1859.     free((char *) sockPtr);
  1860. }
  1861.  
  1862.  
  1863. /*
  1864.  *----------------------------------------------------------------------
  1865.  *
  1866.  * Sock_ScanList --
  1867.  *
  1868.  *    Called to scan a list of sockets of given protocol type.
  1869.  *
  1870.  * Results:
  1871.  *    The next socket on the list or NULL if the list is empty or
  1872.  *    the end of the list has been reached. The value should be
  1873.  *    passed in to the routine on the next call.
  1874.  *
  1875.  * Side effects:
  1876.  *    None.
  1877.  *
  1878.  *----------------------------------------------------------------------
  1879.  */
  1880.  
  1881. Sock_SharedInfo *
  1882. Sock_ScanList(protoIndex, sockPtr)
  1883.     int        protoIndex;        /* Search the list of sockets belonging
  1884.                      * to this protocol. */
  1885.     Sock_SharedInfo    *sockPtr;    /* Used to keep track of the position
  1886.                      * in the scan. */
  1887. {
  1888.     if (protoIndex < 0 || protoIndex > MAX_PROTO_INDEX) {
  1889.     panic("Sock_ScanInit: bad protocol index %d\n", 
  1890.             protoIndex);
  1891.     }
  1892.  
  1893.     if (sockPtr == (Sock_SharedInfo *) NULL) {
  1894.     /*
  1895.      * Start of a scan. Return the first socket in the list or
  1896.      * NULL if the list is empty.
  1897.      */
  1898.     if (!List_IsEmpty(&protoInfo[protoIndex].list)) {
  1899.         sockPtr = (Sock_SharedInfo *) 
  1900.                 List_First(&protoInfo[protoIndex].list);
  1901.     } 
  1902.     } else {
  1903.     /*
  1904.      * Continuing a scan. Return the next socket or NULL if the
  1905.      * current socket is at the end of the list.
  1906.      */
  1907.     sockPtr = (Sock_SharedInfo *) List_Next(&sockPtr->protoLinks);
  1908.     if (List_IsAtEnd(&protoInfo[protoIndex].list, &sockPtr->protoLinks)) {
  1909.         sockPtr = (Sock_SharedInfo *) NULL;
  1910.     }
  1911.     }
  1912.     return(sockPtr);
  1913. }
  1914.  
  1915.  
  1916. /*
  1917.  *----------------------------------------------------------------------
  1918.  *
  1919.  * NoOp --
  1920.  *
  1921.  *    A dummy routine that is used when a protocol does not implement
  1922.  *    a certain socket-related function.
  1923.  *
  1924.  * Results:
  1925.  *    None.
  1926.  *
  1927.  * Side effects:
  1928.  *    None.
  1929.  *
  1930.  *----------------------------------------------------------------------
  1931.  */
  1932.  
  1933. /*VARARGS*/
  1934. static void
  1935. NoOp()
  1936. {
  1937.     return;
  1938. }
  1939.  
  1940.  
  1941. /*
  1942.  *----------------------------------------------------------------------
  1943.  *
  1944.  * DummyOp --
  1945.  *
  1946.  *    A dummy routine that is used when a protocol does not implement
  1947.  *    a certain socket-related function.
  1948.  *
  1949.  * Results:
  1950.  *    Always returns SUCCESS.
  1951.  *
  1952.  * Side effects:
  1953.  *    None.
  1954.  *
  1955.  *----------------------------------------------------------------------
  1956.  */
  1957.  
  1958. /*VARARGS*/
  1959. static ReturnStatus
  1960. DummyOp()
  1961. {
  1962.     return(SUCCESS);
  1963. }
  1964.  
  1965.  
  1966. /*
  1967.  *----------------------------------------------------------------------
  1968.  *
  1969.  * BadOp --
  1970.  *
  1971.  *    A dummy routine that is used when a protocol does not implement
  1972.  *    a certain socket-related function.
  1973.  *
  1974.  * Results:
  1975.  *    Always returns NET_BAD_OPERATION.
  1976.  *
  1977.  * Side effects:
  1978.  *    None.
  1979.  *
  1980.  *----------------------------------------------------------------------
  1981.  */
  1982.  
  1983. /*VARARGS*/
  1984. static ReturnStatus
  1985. BadOp()
  1986. {
  1987.     return(NET_BAD_OPERATION);
  1988. }
  1989.  
  1990.  
  1991. /*
  1992.  *----------------------------------------------------------------------
  1993.  *
  1994.  * Sock_PrintInfo --
  1995.  *
  1996.  *    Scans the 3 lists of sockets (TCP,UDP,Raw) and prints the contents 
  1997.  *    of each active socket's  data structures.
  1998.  *
  1999.  * Results:
  2000.  *    None.
  2001.  *
  2002.  * Side effects:
  2003.  *    None.
  2004.  *
  2005.  *----------------------------------------------------------------------
  2006.  */
  2007.  
  2008. static char *stateNames[] = {
  2009.     "UNUSED",
  2010.     "CREATED",
  2011.     "HAVE_LOCAL_ADDR",
  2012.     "READY",
  2013.     "LISTENING",
  2014.     "CONNECTING",
  2015.     "CONNECTED",
  2016.     "DISCONNECTING",
  2017.     "DISCONNECTED",
  2018. };
  2019.  
  2020. /*ARGSUSED*/
  2021. int
  2022. Sock_PrintInfo(sigNum, sigCode)
  2023.     int sigNum;        /* Ignored. */
  2024.     int sigCode;    /* Ignored. */
  2025. {
  2026.     Sock_SharedInfo    *sharePtr;    /* Socket with the bad route. */
  2027.  
  2028.     (void) fprintf(stderr, "\nActive Sockets:\n\n");
  2029.  
  2030.     (void) fprintf(stderr, "%13s %10s %10s %10s %13s %13s\n",
  2031.     "TCP: State", "Shared", "ProtoPtr", "#Clients", "local", "remote");
  2032.     LIST_FORALL(&protoInfo[TCP_PROTO_INDEX].list, (List_Links *)sharePtr) {
  2033.     (void) fprintf(stderr,
  2034.         "\n %-13s %10x %10x %10d %8x,%4d  %8x,%4d\n",
  2035.         stateNames[(int)sharePtr->state],
  2036.         sharePtr,
  2037.         sharePtr->protoData,
  2038.         sharePtr->clientCount,
  2039.         sharePtr->local.address,
  2040.         sharePtr->local.port,
  2041.         sharePtr->remote.address,
  2042.         sharePtr->remote.port);
  2043.     TCP_PrintInfo(sharePtr->protoData);
  2044.     }
  2045.     (void) fprintf(stderr, "\n");
  2046.  
  2047.     if (!List_IsEmpty(&protoInfo[UDP_PROTO_INDEX].list)) {
  2048.     (void) fprintf(stderr, "%13s %10s %10s %13s %13s\n",
  2049.         "UDP: Shared", "State", "#Clients", "local", "remote");
  2050.     LIST_FORALL(&protoInfo[UDP_PROTO_INDEX].list, (List_Links *)sharePtr) {
  2051.         (void) fprintf(stderr,
  2052.         "%10x %10s %10d %8x,%d  %8x,%d\n",
  2053.         sharePtr,
  2054.         stateNames[(int)sharePtr->state],
  2055.         sharePtr->clientCount,
  2056.         sharePtr->local.address,
  2057.         sharePtr->local.port,
  2058.         sharePtr->remote.address,
  2059.         sharePtr->remote.port);
  2060.     }
  2061.     (void) fprintf(stderr, "\n");
  2062.     }
  2063.  
  2064.     if (!List_IsEmpty(&protoInfo[RAW_PROTO_INDEX].list)) {
  2065.     (void) fprintf(stderr, "%13s %10s %10s %13s %13s\n",
  2066.         "Raw: Shared", "State", "#Clients", "local", "remote");
  2067.     LIST_FORALL(&protoInfo[RAW_PROTO_INDEX].list, (List_Links *)sharePtr) {
  2068.         (void) fprintf(stderr,
  2069.         "%10x %10s %10d %8x,%d  %8x,%d\n",
  2070.         sharePtr,
  2071.         stateNames[(int)sharePtr->state],
  2072.         sharePtr->clientCount,
  2073.         sharePtr->local.address,
  2074.         sharePtr->local.port,
  2075.         sharePtr->remote.address,
  2076.         sharePtr->remote.port);
  2077.     }
  2078.     (void) fprintf(stderr, "\n");
  2079.     }
  2080. }
  2081.